package com.peng.wx_official_account.service.impl;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.peng.wx_official_account.entity.dto.WeChatData;
import com.peng.wx_official_account.entity.dto.WeChatPushDto;
import com.peng.wx_official_account.service.WeChatService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

@Slf4j
public abstract class WeChatServiceImpl implements WeChatService {

    private final WeChatData weChatData;

    private final RestTemplate restTemplate = new RestTemplate();

    public WeChatServiceImpl(WeChatData weChatData) {
        this.weChatData = weChatData;
    }

    /**
     * Push msd data boolean.
     * 微信公众号消息推送接口
     *
     * @return the boolean
     */
    public abstract boolean pushMsdData(WeChatPushDto data);

    @Override
    public void check(HttpServletRequest request, HttpServletResponse response, String signature, String timestamp, String nonce, String echostr) {
        try {
            if (checkSignature(signature, timestamp, nonce)) {
                PrintWriter out = response.getWriter();
                out.print(echostr);
                out.close();
            } else {
                log.error("微信接入校验失败！");
            }
        } catch (IOException e) {
            log.error("微信check出错！");
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    @Override
    public void refreshToken() {
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx705f1d25c331e01d&secret=b7f6f2941911ccc0b8c0e9f12e49533e";
        String response = restTemplate.getForObject(url, String.class);

        //转换获得token并存到对象中
        JSONObject jsonObject = JSONUtil.parseObj(response);
        if (StringUtils.isNotBlank(jsonObject.getStr("errcode"))) {
            log.error("WeChat-Token刷新失败,请求范围为：{}", response);
        } else {
            String token = jsonObject.getStr("access_token");
            weChatData.setToken(token);
            log.info("WeChat-Token刷新成功,新的Token为：{}", token);
        }
    }

    private boolean checkSignature(String signature, String timestamp, String nonce) {
        log.info("微信checking");
        String token = "ljp";

        String[] arr = {token, timestamp, nonce};
        //将token、timestamp、nonce三个参数进行字典排序
        Arrays.sort(arr);

        StringBuilder builder = new StringBuilder();
        Arrays.stream(arr).forEach(builder::append);

        MessageDigest md;
        String tempStr;

        try {
            md = MessageDigest.getInstance("SHA-1");
            //将三个参数字符串拼接成一个字符串进行sha1加密
            byte[] digest = md.digest(builder.toString().getBytes());

            StringBuilder tempBuilder = new StringBuilder();
            for (byte b : digest) {
                tempBuilder.append(byteToHexStr(b));
            }

            tempStr = tempBuilder.toString();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }

        return tempStr.equals(signature.toUpperCase());
    }

    private String byteToHexStr(byte mByte) {
        char[] Digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
        char[] temArr = new char[2];

        temArr[0] = Digit[(mByte >>> 4) & 0X0F];
        temArr[1] = Digit[mByte & 0X0F];

        return new String(temArr);
    }

}
